#include<iostream>
#include<assert.h>
#include<vector>
#include <time.h>
using namespace std;

enum Colour
{
	RED,
	BLACK
};

template<class T>
struct RBTreeNode
{
	//RBTreeNode(T data)
	RBTreeNode(const T& data)
		: _left(nullptr)
		, _right(nullptr)
		, _parent(nullptr)
		, _col(RED)
		, _data(data)
	{}

	RBTreeNode* _left;
	RBTreeNode* _right;
	RBTreeNode* _parent;
	Colour _col;
	T _data;
};

template<class T>
class RBTree
{
	typedef RBTreeNode<T> Node;
public:
	RBTree()
		: _root(nullptr)
	{}

	//左单旋
	void RotateL(Node* root)
	{
		Node* Pparent = root->_parent;
	 
		Node* rootR = root->_right;
		Node* rootRL = rootR->_left;
	 
		root->_right = rootR->_left;
		if (rootRL)
			rootRL->_parent = root;
	 
		rootR->_left = root;
		root->_parent = rootR;
	 
		//root->_bf = rootR->_bf = 0;
		//if(rootRL)
		//	rootRL->_bf = 0;
	 
		if (root == _root)
		{
			_root = rootR;
			_root->_parent = nullptr;
		}
		else
		{
			if (Pparent->_left == root)
			{
				Pparent->_left = rootR;
				rootR->_parent = Pparent;
			}
			else if (Pparent->_right == root)
			{
				Pparent->_right = rootR;
				rootR->_parent = Pparent;
			}
			else
			{
				assert(false);
			}
		}
	}
	//右单旋
	void RotateR(Node* root)
	{
		Node* Pparent = root->_parent;
	 
		Node* rootL = root->_left;
		Node* rootLR = rootL->_right;
	 
		root->_left = rootL->_right;
		if (rootLR)
			rootLR->_parent = root;
	 
		rootL->_right = root;
		root->_parent = rootL;
	 
		//root->_bf = rootL->_bf = 0;
		//if(rootLR)
		//	rootLR->_bf = 0;
	 
		if (root == _root)
		{
			_root = rootL;
			_root->_parent = nullptr;
		}
		else
		{
			if (Pparent->_left == root)
			{
				Pparent->_left = rootL;
				rootL->_parent = Pparent;
			}
			else if (Pparent->_right == root)
			{
				Pparent->_right = rootL;
				rootL->_parent = Pparent;
			}
			else
			{
				assert(false);
			}
		}
	}
	
	//////左右单旋
	////void RotateLR(Node* root)
	////{
	////	Node* rootL = root->_left;
	////	Node* rootLR = rootL->_right;
	////	int bf = rootLR->_bf;
	//// 
	////	RotateL(rootL);
	////	RotateR(root);
	//// 
	////	if (bf == -1)
	////	{
	////		root->_bf = 1;
	////		rootL->_bf = 0;
	////		if (rootLR)
	////			rootLR->_bf = 0;
	////	}
	////	else if (bf == 1)
	////	{
	////		rootL->_bf = -1;
	////		root->_bf = 0;
	////		if (rootLR)
	////			rootLR->_bf = 0;
	////	}
	////	else if (bf == 0)
	////	{
	////		rootL->_bf = root->_bf = rootLR->_bf = 0;
	////	}
	////	else
	////	{
	////		assert(false);
	////	}
	////}
	//////右左单旋
	////void RotateRL(Node* root)
	////{
	////	Node* rootR = root->_right;
	////	Node* rootRL = rootR->_left;
	//// 
	////	int bf = rootRL->_bf;
	//// 
	////	RotateR(rootR);
	////	RotateL(root);
	//// 
	////	if (bf == -1)
	////	{
	////		root->_bf = -1;
	////		rootR->_bf = 0;
	////		if (rootRL)
	////			rootRL->_bf = 0;
	////	}
	////	else if (bf == 1)
	////	{
	////		rootR->_bf = 1;
	////		root->_bf = 0;
	////		if (rootRL)
	////			rootRL->_bf = 0;
	////	}
	////	else if (bf == 0)
	////	{
	////		rootR->_bf = root->_bf = rootRL->_bf = 0;
	////	}
	////	else
	////	{
	////		assert(false);
	////	}
	////}

	//Insert函数
	bool Insert(T data)
	{
		//第一次插入
		if (_root == nullptr)
		{
			_root = new Node(data);
			//根节点置黑
			_root->_col = BLACK;
			return true;
		}

		Node* cur = _root;
		Node* parent = nullptr;
		while (cur)
		{
			if (data < cur->_data)
			{
				//往右走
				parent = cur;
				cur = cur->_left;
			}
			else if (data > cur->_data)
			{
				//往左走
				parent = cur;
				cur = cur->_right;
			}
			else //相等
			{
				return false;
			}
		}
		//找到位置
		cur = new Node(data);
		if (data < parent->_data)
		{
			parent->_left = cur;
		}
		else
		{
			parent->_right = cur;
		}
		cur->_parent = parent;

		//开始检查红黑树性质是否遭到破坏

		//如果parent为黑，插入完成
		if (parent->_col == BLACK)
		{
			return true;
		}
		//如果parent为红，开始调整
		else
		{	
			while (cur->_parent && cur->_parent->_col == RED) //如果parent为红，开始调整
			{
				//根据cur重置parent、grandparent、uncle
				parent = cur->_parent;
				Node* grandparent = parent->_parent;
				Node* uncle = nullptr;
				if (parent == grandparent->_left)
				{
					uncle = grandparent->_right;
				}
				else
				{
					uncle = grandparent->_left;
				}

				//情况一
				if (uncle && uncle->_col == RED)
				{
					parent->_col = uncle->_col = BLACK;
					grandparent->_col = RED;	

					//grandparent作cur，继续向上调整
					cur = grandparent;
				}
				//情况二、三
				else //uncle不存在/uncle为黑
				{
					//情况二 单旋					 
					//       g
					//    p
					// c
					if (parent == grandparent->_left && cur == parent->_left)
					{
						RotateR(grandparent);
						//变色
						parent->_col = BLACK;
						grandparent->_col = RED;
						break;
					}
					// g
					//    p
					//       c
					else if (parent == grandparent->_right && cur == parent->_right)
					{
						RotateL(grandparent);
						//变色
						parent->_col = BLACK;
						grandparent->_col = RED;
						break;
					}

					//情况三 双旋					 
					//    g
					// p
					//    c
					else if (parent == grandparent->_left && cur == parent->_right)
					{
						RotateL(parent);
						RotateR(grandparent);
						//变色
						cur->_col = BLACK;
						grandparent->_col = RED;
						break;
					}
					// g
					//    p
					// c
					else if (parent == grandparent->_right && cur == parent->_left)
					{
						RotateR(parent);
						RotateL(grandparent);
						//变色
						cur->_col = BLACK;
						grandparent->_col = RED;
						break;
					}
					else
					{
						assert(false);
					}
				}
			}
		}
		
		//根节点置黑
		_root->_col = BLACK;
		return true;

	}

	void InOrder()
	{
		_InOrder(_root);
	}

	void _InOrder(Node* root)
	{
		if (root == NULL)
			return;

		_InOrder(root->_left);
		cout << root->_data << " ";
		_InOrder(root->_right);
	}
	void PrevOrder()
	{
		_PrevOrder(_root);
	}

	void _PrevOrder(Node* root)
	{
		if (root == NULL)
			return;

        cout << root->_data << " ";
		_PrevOrder(root->_left);
		_PrevOrder(root->_right);
	}

	bool IsBalance()
	{
		//检测第二条性质，根节点是否为黑
		//if (_root->_col == RED)------->先检测根节点是否为空再访问其成员
		if (_root && _root->_col == RED)
		{
			return false;
		}

		//计算最左路径黑色节点的数目作基准值
		Node* root = _root;
		int banchmark = 0; //基准值		
		while (root)
		{
			if (root->_col == BLACK)
				banchmark++;

			root = root->_left;
		}

		int blackNum = 0;
		return _IsBalance(_root, blackNum, banchmark);
	}

	bool _IsBalance(Node* root, int blackNum, int banchmark)
	{
		//检测
		
		//检查性质三，各路径黑节点数目是否相同
		if (root == nullptr)
		{
			return blackNum == banchmark;
		}

		if (root->_col == BLACK)
			blackNum++;

		//检查性质三，是否有连续红节点
		if (root->_col == RED && root->_parent->_col == RED)
			return false;

		return _IsBalance(root->_left, blackNum, banchmark)
			&& _IsBalance(root->_right, blackNum, banchmark);
	}

private:
	Node* _root;
};